#ifndef __PAY_NTP_H__
#define __PAY_NTP_H__

#include <Arduino.h>
#include <TimeLib.h>
#include <WIFI.h>
#include <WiFiUdp.h>

WiFiUDP Udp;
const int NTP_PACKET_SIZE = 48;
byte packetBuffer[NTP_PACKET_SIZE];
const int timeZone = 8;

struct TIME_CONFIG {
  uint8_t weeks = 1;
  uint32_t years = 2020;
  uint8_t months = 3;
  uint8_t days = 4;
  uint8_t hours = 15;
  uint8_t minutes = 5;
  uint8_t seconds = 30;
} TIME_NOW;

void boxNTPRefresh(void) {
  TIME_NOW.years = year();
  TIME_NOW.months = month();
  TIME_NOW.days = day();
  TIME_NOW.hours = hour();
  TIME_NOW.minutes = minute();
  TIME_NOW.seconds = second();
  TIME_NOW.weeks = weekday();
}

void sendNTPpacket(IPAddress &address) {
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011; // LI, Version, Mode
  packetBuffer[1] = 0;          // Stratum, or type of clock
  packetBuffer[2] = 6;          // Polling Interval
  packetBuffer[3] = 0xEC;       // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); // NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

time_t getNtpTime(void) {
  IPAddress ntpServerIP; // NTP server's ip address
  while (Udp.parsePacket() > 0) {
  }
  // discard any previously received packets
  Serial.println("Transmit NTP Request");
  // get a random server from the pool
  WiFi.hostByName("time1.aliyun.com", ntpServerIP);
  Serial.print("time1.aliyun.com");
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 = (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-("); //没连接到NTP服务器
  return 0;                              // return 0 if unable to get the time
}

void payNTPInit() {
  // NTP网络时钟就绪
  Udp.begin(8888);
  setSyncProvider(getNtpTime);
  setSyncInterval(300);
}

#endif